package ru.averta.notes.domain;

import org.hibernate.search.annotations.*;
import ru.averta.notes.domain.abstr.BusinessObject;
import ru.averta.notes.domain.abstr.UserableObject;
import ru.averta.notes.domain.flags.IArchivable;
import ru.averta.notes.domain.flags.IFavoritable;
import ru.averta.notes.domain.flags.IViewable;
import ru.averta.notes.service.search.bridge.TagFieldBridge;

import javax.persistence.*;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Entity
@Indexed
public class Site extends UserableObject implements BusinessObject, IViewable, IFavoritable, IArchivable {

    @Column(name = "TITLE")
    @Field(store = Store.YES, termVector = TermVector.WITH_POSITION_OFFSETS)
    @Boost(3.0f)
    private String title;

    @Column(name = "LAST_MODIFIED")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModified = new Date();

    @Field(index = Index.UN_TOKENIZED)
    @Column(name = "IS_FAVORITE")
    private boolean favorite;

    @Field(index = Index.UN_TOKENIZED)
    @Column(name = "IS_ARCHIVED")
    private boolean archived;

    @OneToMany(fetch = FetchType.EAGER, mappedBy="site") //Подгружаем все оценки объекта сразу
    @IndexedEmbedded(depth = 1)
    private Set<CoolMark> marks = new HashSet<CoolMark>();

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SITE_CONTENT_ID")
    @IndexedEmbedded(depth = 1)
    private SiteContent siteContent;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "URL_ID")
    private Url url;

    /** Данное свойство необходимо только для Hibernate Criteria API */
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "baseSubject")
    private Collection<TagConnector> tagConnectors;

    /** Данный метод осуществляет индексацию тегов Lucene */
    @Field
    @FieldBridge(impl = TagFieldBridge.class)
    private Site getLuceneTags() { return this; }

    /** Пустой конструктор для hibernate */
    public Site() {
    }

    /** Конструктор, который определяет страницу сайта. Title опционально */
    public Site(Url url, String title, User user) {
        this.url = url;
        this.title = title;
        setUser(user);
    }

    /*
    * GET / SET
    */

    public SiteContent getSiteContent() {
        return siteContent;
    }

    public void setSiteContent(SiteContent siteContent) {
        if (this.siteContent != null) this.siteContent.setSite(null);
        this.siteContent = siteContent;
        this.siteContent.setSite(this);
    }

    public Collection<CoolMark> getMarks() {
        return marks;
    }

    @Override
    public long getId() {
        return super.getId();
    }

    @Override
    @IndexedEmbedded(depth=1)
    public User getUser() {
        return super.getUser();
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        if (title != null && title.length() > 255) {
            this.title = title.substring(0, 252) + "...";
        } else {
            this.title = title;
        }
    }

    public void setLastModified(Date lastModified) {
        this.lastModified = lastModified;
    }

    @Override
    public boolean isFavorite() {
        return favorite;
    }

    public void setFavorite(boolean isFavorite) {
        this.favorite = isFavorite;
    }

    @Override
    public boolean isArchived() {
        return archived;
    }

    public void setArchived(boolean archived) {
        this.archived = archived;
    }

    @Override
    public Date getLastModified() {
        return lastModified;
    }

    /**
     * Специфические данные site'а
     */
    public Url getUrl() {
        return url;
    }

    public void setUrl(Url url) {
        this.url = url;
    }

    /*@Field
    @Column(name="URL"*//*, nullable=false*//*) //TODO
    private String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }*/
}
